package pe.tnova.core.db;

import java.util.Arrays;
import java.util.List;

import javax.persistence.Parameter;
import javax.persistence.Query;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import pe.tnova.library.util.CharPoolUtil;
import pe.tnova.library.util.validate.ValidateUtil;

public class DAOUtil {

	private static final Logger log = LoggerFactory.getLogger(DAOUtil.class);
	/**
	 * %
	 */
	public static String SQL_PORCENT = "%";
	/**
	 * IN
	 */
	public static String SQL_IN = " in ";
	/**
	 * AND
	 */
	public static String SQL_AND = " and ";
	/**
	 * OR
	 */
	public static String SQL_OR = " or ";
	/**
	 * Where
	 */
	public static String SQL_WHERE = " where ";
	/**
	 * p
	 */
	public static String SQL_SE = " p";
	/**
	 * p.
	 */
	public static String SQL_SEA = " p.";
	/**
	 * :
	 */
	public static String SQL_FILTRO = ":";
	/**
	 * menos
	 */
	public static String SQL_MENOS = " < ";
	/**
	 * mas
	 */
	public static String SQL_MAS = " > ";
	/**
	 * select
	 */
	public static String SQL_SELECT = " select ";
	/**
	 * from
	 */
	public static String SQL_FROM = " from ";
	/**
	 * igual
	 */
	public static String SQL_EQ = " = ";
	/**
	 * count
	 */
	public static String SQL_COUNT = " count ";
	/**
	 * like
	 */
	public static String SQL_LIKE = " like ";
	/**
	 * asc
	 */
	public static String SQL_ASC = " asc ";
	/**
	 * desc
	 */
	public static String SQL_DESC = " desc ";
	/**
	 * desigual
	 */
	public static String SQL_EN = " <> ";
	/**
	 * orden
	 */
	public static String ORDER_BY = " order by ";

	public static final String JOIN = " join ";

	public static final String LEFT_JOIN = " left join  ";

	public static final String LEFT_OUTER_JOIN = " left outer join  ";

	public static final String INNER_JOIN = " inner join ";

	public static final String LEFT_JOIN_FETCH = " LEFT JOIN FETCH ";

	public static final String DISTINCT = " DISTINCT ";

	public static final String BETWEEN = " BETWEEN $0$ AND $1$ ";

	public static final String TOKEMN1 = "0";
	public static final String TOKEMNB1 = "$0$";

	public static final String TOKEMN2 = "1";
	public static final String TOKEMNB2 = "$1$";
	
	public static final Object LISTA_LIMItADA_CBO = "limite_cbo";
	
	public static final Object LISTA_COMPLETA = "lista_full";

	/**
	 * Agrega condicion
	 * 
	 * @param sbQuery
	 * @param condicion
	 * @param param
	 */
	public static boolean establecerCondicion(StringBuffer sbQuery, String condicion, Object param) {
		if (sbQuery.toString().indexOf(SQL_WHERE) == -1 && ValidateUtil.isNotNull(param)) {
			sbQuery.append(SQL_WHERE);
		}
		if (ValidateUtil.isNotNull(param)) {
			sbQuery.append(condicion);
			sbQuery.append(SQL_AND);
			return true;
		} else
			return false;
	}

	/**
	 * Agrega condicion IN
	 * 
	 * @param sbQuery
	 * @param condicion
	 * @param param
	 */
	public static boolean establecerCondicionIN(StringBuffer sbQuery, String condicion, List<?> param) {
		if (sbQuery.toString().indexOf(SQL_WHERE) == -1 && ValidateUtil.isNotNull(param)) {
			sbQuery.append(SQL_WHERE);
		}
		if (param != null && !param.isEmpty()) {
			sbQuery.append(condicion);
			sbQuery.append(SQL_AND);
			return true;
		} else
			return false;
	}

	/**
	 * Agrega parametro
	 * 
	 * @param query
	 * @param nombCampo
	 * @param param
	 */
	public static void establecerParam(Query query, String nombCampo, Object param) {
		establecerParam(query, nombCampo, param, false, false);
	}

	/**
	 * Agrega parametro IN
	 * 
	 * @param query
	 * @param nombCampo
	 * @param param
	 */
	public static void establecerParamIN(Query query, String nombCampo, List<?> param) {
		if (param != null && !param.isEmpty()) {
			query.setParameter(nombCampo, param);
		}
	}
	/**
	 * Agrega parametro like mayuscula
	 * 
	 * @param query
	 * @param nombCampo
	 * @param param
	 * @param esLike
	 * @param convertirMayuscula
	 */
	public static void establecerParam(Query query, String nombCampo, Object param, boolean esLike, boolean convertirMayuscula) {
		if (ValidateUtil.isNotNull(param)) {
			if (esLike) {
				query.setParameter(nombCampo, SQL_PORCENT + (convertirMayuscula ? param.toString().toUpperCase() : param) + SQL_PORCENT);
			} else {
				query.setParameter(nombCampo, param);
			}
		}
	}

	/**
	 * Asignar al query inicio y fin
	 * 
	 * @param qy
	 * @param inicio
	 * @param fin
	 */
	public static void setPaginador(Query qy, int inicio, int fin) {
		if (inicio > CharPoolUtil.NUMBER_0 && fin > CharPoolUtil.NUMBER_0) {
			qy.setFirstResult(inicio);
			qy.setMaxResults(fin);
		}
	}

	public static void setOrder(StringBuffer sbQuery, String strCampo, String order) {
		if (ValidateUtil.isNotNull(strCampo) && ValidateUtil.isNotNull(order)) {
			sbQuery.append(ORDER_BY + strCampo + order);
		}
	}

	/**
	 * Print query
	 * 
	 * @param q
	 */
	public static void printParameterQuery(Query q) {
		if (log.isDebugEnabled()) {
			log.debug("printParameterQuery");
			List<Parameter<?>> listaParametros = Arrays.asList(q.getParameters().toArray(new Parameter<?>[0]));
			for (Parameter<?> parameter : listaParametros) {
				log.debug(parameter.getName() + SQL_FILTRO + q.getParameterValue(parameter.getName()).toString());
			}
		}
	}

	/**
	 * Establece los inner joins para el query
	 * 
	 * @param strbfSqlQuery
	 * @param innerjoin
	 */
	public static void establecerCondicionInnerJoins(StringBuffer sbQuery, JoinEntidad... innerjoin) {
		int existe = sbQuery.toString().indexOf(SQL_WHERE);
		String strCondicionales = CharPoolUtil.VACIO;
		if (existe >= CharPoolUtil.NUMBER_0 && ValidateUtil.isNotNull(innerjoin)) {
			String strTemp1 = sbQuery.toString();
			strCondicionales = strTemp1.substring(existe, strTemp1.length());
			strTemp1 = strTemp1.substring(existe);
			sbQuery = new StringBuffer(strTemp1);
		}
		for (JoinEntidad ij : innerjoin) {
			sbQuery.append(ij.getInner() + " ");
			sbQuery.append(SQL_SEA + ij.getEntidad() + " " + ij.getPerfijo());
			if (ValidateUtil.isNotNull(ij.getAtributo())) {
				sbQuery.append(ij.getPerfijo() + CharPoolUtil.PERIOD + ij.getAtributo() + " ");
				sbQuery.append(ij.getCondicional() + " ");
				sbQuery.append(SQL_FILTRO + ij.getAtributo() + " ");
			}
		}
		sbQuery.append(strCondicionales);
	}

	/**
	 * Establece los valores de la conuslta sobre los joins
	 * 
	 * @param qy
	 * @param innerjoin
	 */
	public static void establecerInnerJoinsParam(Query qy, JoinEntidad[] innerjoin) {
		for (JoinEntidad joinEntidad : innerjoin) {
			if (ValidateUtil.isNotNull(joinEntidad.getAtributo()) && ValidateUtil.isNotNull(joinEntidad.getValue())) {
				qy.setParameter(joinEntidad.getAtributo(), joinEntidad.getValue());
			}
		}
	}


}
